package com.sqi.reactive.common.controller

import com.sqi.reactive.common.annoation.IgnoreAuth
import com.sqi.reactive.common.auth.RequestContext
import com.sqi.reactive.common.auth.Subject
import com.sqi.reactive.common.token.TokenHelper
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import io.swagger.annotations.ApiOperation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.server.reactive.ServerHttpResponse
import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Mono

/**
 * @author sjl
 * @date 2020/6/19
 */
@Suppress("SpringJavaAutowiredMembersInspection")
@RequestMapping("/auth")
abstract class AuthController {
    @Autowired
    lateinit var tokenHelper: TokenHelper

    @Autowired
    lateinit var requestContext: RequestContext

    @RequestMapping(value = ["/error"], method = [RequestMethod.POST, RequestMethod.GET])
    @ResponseBody
    @IgnoreAuth
    fun error(response: ServerHttpResponse): Mono<ResultHandler<String>> = doError(response)

    open fun doError(response: ServerHttpResponse): Mono<ResultHandler<String>> =
        Mono.just(ResultHandler(ResultHandler.ResultHandlerType.LOGIN_ERROR))

    @ApiOperation(value = "用户登录接口", notes = "返回jwt token")
    @PostMapping("/login")
    @ResponseBody
    @IgnoreAuth
    fun login(@RequestBody loginForm: LoginForm): Mono<ResultHandler<Map<String, String>>> =
        doLogin(loginForm).filter { it != null }
            .map(tokenHelper::generate)
            .map { token -> ResultHandler(ResultHandler.ResultHandlerType.SUCCESS, mapOf(Pair("token", token))) }
            .switchIfEmpty(Mono.just(ResultHandler(0, "用户名或密码错误！")))


    abstract fun doLogin(loginForm: LoginForm): Mono<Subject>

    @ApiOperation(value = "获取当前登录用户信息")
    @GetMapping("/userinfo")
    @ResponseBody
    fun userinfo(): Mono<ResultHandler<Subject?>> {
        return resultHandler(
                requestContext.loginUser
        )
    }
}

@ApiModel(value = "LoginForm", description = "用户登录参数接收对象")
data class LoginForm(
        @ApiModelProperty(name = "username", value = "用户登录名", required = true)
        val username: String,
        @ApiModelProperty(name = "password", value = "用户登录密码", required = true)
        val password: String
)